package drds.plus.datanode.select;

import drds.plus.datanode.configuration.DataSourceWrapper;
import drds.plus.datanode.executor.Executor;
import drds.plus.datasource.api.DataSource;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 只有一个数据源的DBSelector
 */
public class OneSelector extends AbstractSelector {

    private final DataSourceHolder dataSourceHolder;
    private final Map<String, DataSource> dataSourceIdToDataSourceMap;

    public OneSelector(DataSourceWrapper dataSourceWrapper) {
        this.dataSourceHolder = new DataSourceHolder(dataSourceWrapper);
        dataSourceIdToDataSourceMap = new LinkedHashMap<String, DataSource>();
        dataSourceIdToDataSourceMap.put(dataSourceWrapper.getDataSourceId(), dataSourceWrapper.getDataSource());
    }

    public DataSourceWrapper select() {
        return dataSourceHolder.dataSourceWrapper;
    }

    public Map<String, DataSource> getDataSourceIdToDataSourceHolderMap() {
        return dataSourceIdToDataSourceMap;
    }

    protected <T> T selectDataSourceHolderAndGetConnectionWrapperAndExecuteAndRetryIfFailed(Map<javax.sql.DataSource, SQLException> failedDataSourceToSQLExceptionMap, Executor<T> tryer, int times, Object... args) throws SQLException {
        List<SQLException> sqlExceptionList;
        if (failedDataSourceToSQLExceptionMap != null && failedDataSourceToSQLExceptionMap.containsKey(dataSourceHolder.dataSourceWrapper)) {
            sqlExceptionList = new ArrayList<SQLException>(failedDataSourceToSQLExceptionMap.size());
            sqlExceptionList.addAll(failedDataSourceToSQLExceptionMap.values());
            return tryer.onSqlException(sqlExceptionList, this.exceptionSorter, args);
        }
        //
        try {
            return createConnectionWrapperAndExecute(dataSourceHolder, failedDataSourceToSQLExceptionMap, tryer, times, args);
        } catch (SQLException e) {
            sqlExceptionList = new ArrayList<SQLException>(1);
            sqlExceptionList.add(e);
        }
        return tryer.onSqlException(sqlExceptionList, this.exceptionSorter, args);
    }

    public DataSourceWrapper get(String dataSourceId) {
        return dataSourceHolder.dataSourceWrapper.getDataSourceId().equals(dataSourceId) ? dataSourceHolder.dataSourceWrapper : null;
    }

    protected DataSourceHolder findDataSourceHolderByDataSourceIndex(String dataSourceIndex) {
        return dataSourceHolder.dataSourceWrapper.isMatchDataSourceIndex(dataSourceIndex) ? dataSourceHolder : null;
    }
}
